package gui;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.GregorianCalendar;

import javax.imageio.ImageIO;
import javax.swing.JLabel;
import javax.swing.JScrollPane;

import building.AuxInfo;
import building.Cell;
import building.InfoAgent;

/**
 * <p>
 * <B>Title:</b> Fire Evacuation
 * </p>
 * Visualization of the map. There are several elements to depict, as door,
 * fire,smoke, the agents, etc.<br>
 * This class *should be* modified and improved in order to show as good as
 * possible all the changes in the simulation. <br>
 * 
 * @author Carolina Arce & Caterina Bruno
 */
public class MapVisualizer extends JScrollPane {

	private int inset = 50;
	int nrows;
	int ncols;
	private Map t;
	java.awt.Point start, end;
	int dx, dy, gap;
	private Rectangle2D.Double cellBorder;
	private Rectangle2D.Double building;
	private Ellipse2D.Double agentFigure;
	private JLabel[][][] labelMatrix;
	private int nfloors;
	private float fogLevel = 0.99f;
	/**** cate ***/
	private GregorianCalendar startTime;
	private AuxInfo info;
	/**** cate ***/

	/*** carolina **********************************/
	private BufferedImage bi;
	int w, h;
	private URL imageSrc;
	private boolean stop = false;

	/*************************************/

	public MapVisualizer(Map map, AuxInfo auxInfo) {
		try {
			startTime = null;
			info = auxInfo;

			this.t = map;
			this.nfloors = t.nfloor;
			nrows = t.length;
			ncols = t.width;
			labelMatrix = new JLabel[nfloors][nrows][ncols];
			System.out.println("mapvisualizer" + nfloors);

			Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

			start = new Point(inset, inset);
			end = new Point(screenSize.width - inset * 2, screenSize.height
					- inset * 2);
			dx = ((end.x - start.x) / (nrows * nfloors)) - 4;
			dy = (end.y - start.y) / (ncols * nfloors);

			gap = 5;
			cellBorder = new Rectangle2D.Double(gap + 10, gap + 10, dx, dy);

			agentFigure = new Ellipse2D.Double(gap + 10 + (dx / 4), gap + 10
					+ (dy / 4), (dx / 2), (dy / 2));

			for (int f = 0; f < nfloors; f++)
				for (int i = 0; i < nrows; i++)
					for (int j = 0; j < ncols; j++) {
						t.getCell(i, j, f).setFloor(f);
					}
			// t[i][j][f].setFloor(f);

			this.repaint();
		} catch (Exception e) {
			e.toString();
			System.out.println("Exception in mapvisualizer");
		}

	}

	private void drawBuilding(Graphics2D g2d, int x, int y, building.Cell c) {
		// g2d.translate(dx * x, dy * y);
		try {
			if (c.isDiscovered())
				g2d.setPaint(Color.CYAN.darker());
			else
				g2d.setPaint(Color.BLUE.darker());
			g2d.fill(cellBorder);
			g2d.setPaint(Color.DARK_GRAY);
			g2d.draw(cellBorder);
			// String msg = c.getFireIntensityString();
			g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
					java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
			java.awt.Font font = new java.awt.Font("Serif",
					java.awt.Font.PLAIN, 11);
			// g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
			// 0.99f));
			g2d.setFont(font);
			g2d.setPaint(Color.WHITE);
			// g2d.drawString(msg,dx-40,dy);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void drawDoor(Graphics2D g2d, int x, int y, building.Cell c) {
		// g2d.translate(dx * x, dy * y);
		try {
			
				g2d.setPaint(Color.white);
			
			g2d.fill(cellBorder);
			g2d.setPaint(Color.BLACK);
			g2d.draw(cellBorder);
			String msg = "door";
			g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
					java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
			java.awt.Font font = new java.awt.Font("Serif",
					java.awt.Font.PLAIN, 11);
			g2d.setFont(font);
			g2d.setPaint(Color.WHITE);
			g2d.drawString(msg, dx - 20, dy);
			URL myURL;
			if(c.getFloor()==0)
				myURL = new URL("file", "", "door.jpg");
			else 
				myURL = new URL("file", "", "exit-door.jpg");
			ImageDrawing(myURL);
			// String msg = "fire"; //c.getGarbagePointsString();
			g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
					java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
			//g2d.drawImage(bi, (dx / 8), (dy / 4), (dx), (dy), null);
		//	g2d.drawImage(bi, 10 + (dx / 4), 10 + (dy / 4), (dx / 2), (dy),
			//		null);
			g2d.drawImage(bi, 10+(dx / 8),  10+(dy / 4), (dx), (dy), null);

			drawStreetAgents(g2d, x, y, c);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void drawStairs(Graphics2D g2d, int x, int y, building.Cell c) {
		// g2d.translate(dx * x, dy * y);
		try {
			// if (c.isDiscovered())
			g2d.setPaint(Color.white);
			// else
			// g2d.setPaint(Color.BLACK.darker());
			g2d.fill(cellBorder);
			g2d.setPaint(Color.white);
			g2d.draw(cellBorder);

			URL myURL = new URL("file", "", "stairs.jpg");

			ImageDrawing(myURL);
			// String msg = "fire"; //c.getGarbagePointsString();
			g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
					java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
			//g2d.drawImage(bi, (dx / 8), (dy / 4), (dx), (dy), null);
			g2d.drawImage(bi, 10+(dx / 8),  10+(dy / 4), (dx), (dy), null);
			java.awt.Font font = new java.awt.Font("Serif",
					java.awt.Font.PLAIN, 11);
			g2d.setFont(font);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (c.isThereAnAgent()) {
			drawStreetAgents(g2d, x, y, c);
		}

	}

	private void drawFireCenter(Graphics2D g2d, int x, int y, building.Cell c) {

		try {
			if (c.isDiscovered())
				g2d.setPaint(Color.WHITE);
			else
				g2d.setPaint(Color.GRAY);
			g2d.fill(cellBorder);
			g2d.setPaint(Color.white);
			g2d.draw(cellBorder);

			URL myURL = new URL("file", "", "Fire.jpg");
			// URL myURL = new URL("file","","Fire.gif");
			ImageDrawing(myURL);
			String msg = "" + c.getFireIntensityString();
			g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
					java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
			g2d.drawImage(bi, 10 + (dx / 4), 10 + (dy / 4), (dx / 2), (dy),
					null);

			java.awt.Font font = new java.awt.Font("Serif",
					java.awt.Font.PLAIN, 11);
			g2d.setFont(font);
			g2d.setPaint(Color.BLACK);
			g2d.drawString(msg, dx - 60, dy);
			drawStreetAgents(g2d, x, y, c);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void drawSmoke(Graphics2D g2d, int x, int y, building.Cell c) {
		try {
			g2d.setPaint(Color.WHITE);
			g2d.fill(cellBorder);
			g2d.setPaint(Color.DARK_GRAY);
			g2d.draw(cellBorder);

			URL myURL = new URL("file", "", "Smoke.jpg");
			ImageDrawing(myURL);
			g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
					java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
			g2d.drawImage(bi, 15, 15, (dx), (dy), null);
			g2d.setComposite(AlphaComposite.getInstance(
					AlphaComposite.SRC_OVER, 0.7f));

			g2d.setPaint(Color.BLACK);
			drawStreetAgents(g2d, x, y, c);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void moveXY(Graphics2D g2d, int x, int y) {
		g2d.translate(dx * x, dy * y);
	}

	private Color getColor(InfoAgent agent) {
		float h;
		boolean isInjured = false;

		if(agent.died==true)
			return new Color(0, 0, 0); // dead- black

		if (agent.getAgentType() == InfoAgent.CIVILIAN
				|| agent.getAgentType() == InfoAgent.EVACUATOR) {
			h = agent.getHealty();

			isInjured = agent.getInjured();
			

			if (agent.getAgentType() == InfoAgent.EVACUATOR && !isInjured)
				return new Color(0, 0, 255); //blu
			
			if (!isInjured) {

				if (h > 80.0) {

					return new Color(200, 252, 0); // green
				} else if (h <= 80 && h > 60) {
					return new Color(255, 255, 0); // yellow
				} else if (h <= 60 && h > 45) {
					return new Color(255, 127, 0); // orange
				} else if (h <= 45 && h > 20) {
					return new Color(255, 0, 0); // red
				}
				return new Color(0, 0, 0); // dead- black
			} else // se � ferito
			{

				return new Color(200, 200, 200); //gray injured
			}
		}

		/*if (agent.getAgentType() == InfoAgent.PARAMEDIC)
			return Color.white;*/

		return new Color(255, 0, 0);

	}

	private void drawStreetAgents(Graphics2D g2d, int x, int y, building.Cell c) {
		int f = c.getFloor();

		if (c.isThereAnAgent()) {

			c.setDiscovered(true);

			InfoAgent agent = (InfoAgent) c.getAgent();

			if (imBlocked(x, y, f, t) && agent.died==false) {
				g2d.setPaint(new Color(255,20,147));
				System.out.println("agent in pos " + x + " " + y + " " + f
						+ " is blocked");
			} else
				g2d.setPaint(getColor(agent));
			g2d.translate((dx / 6), (dy / 6));
			g2d.fill(agentFigure);
			g2d.translate(-(dx / 6), -(dy / 6));

			try {
				char currentType;
				currentType = agent.getAgent().toCharArray()[0];
				String msg = agent.getAID().getLocalName();// "" + currentType;
															// //
															// agent.getAID().getLocalName();//
															// cambiar por la
															// salud
				g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
						java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
				java.awt.Font font = new java.awt.Font("Serif",
						java.awt.Font.PLAIN, 11);

				if (agent.panic == 80) {
					msg = msg + "  panic";
				}

				if (agent.p_injured) {
					msg = msg + "  p_inj";
				}

				g2d.setFont(font);
				g2d.setPaint(Color.BLACK);
				g2d.drawString(msg, dx - 40, dy);

			} catch (Exception e) {
				System.out.println("diseno del civilian" + e.toString());
			}
		}

	}

	private void drawStreet(Graphics2D g2d, int x, int y, building.Cell c) {
		// g2d.translate(dx * x, dy * y);
		try {
			int f = c.getFloor();
			g2d.setPaint(Color.LIGHT_GRAY);
			g2d.fill(cellBorder);
			g2d.setPaint(Color.DARK_GRAY);
			g2d.draw(cellBorder);
			drawStreetAgents(g2d, x, y, c);

			if (c.isThereAnAgent()) {
				if (c.getAgent().getAgentType() == InfoAgent.CIVILIAN) {

					GridBagConstraints constraints = new GridBagConstraints();
					constraints.fill = GridBagConstraints.BOTH;

					constraints.gridx = x;
					constraints.gridy = y;
					final JLabel label = new JLabel();
					label.setPreferredSize(new Dimension(dx, dy));
					// System.err.println("AGENT IN  X " +x+ " Y " + y);

					label.addMouseListener(new ClickHandler(x, y, c.getAgent()));

					labelMatrix[f][x][y] = label;
					this.add(label, constraints);

				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void paintComponent(Graphics g) {
		clear(g);
		Graphics2D g2d = (Graphics2D) g;

		for (int f = 0; f < t.nfloor; f++) {
			for (int i = 0; i < t.length; i++) {
				for (int j = 0; j < t.width; j++) {
					g2d.draw(cellBorder);
					if (t.getCell(i, j, f).getCellType() == Cell.FREE)
						drawStreet(g2d, i, j, t.getCell(i, j, f));
					if (t.getCell(i, j, f).getCellType() == Cell.STAIRS)
						drawStairs(g2d, i, j, t.getCell(i, j, f));
					if (t.getCell(i, j, f).getCellType() == Cell.FIRE)
						drawFireCenter(g2d, i, j, t.getCell(i, j, f));
					if (t.getCell(i, j, f).getCellType() == Cell.OBJECT)
						drawBuilding(g2d, i, j, t.getCell(i, j, f));
					if (t.getCell(i, j, f).getCellType() == Cell.DOOR)
						drawDoor(g2d, i, j, t.getCell(i, j, f));
					if (t.getCell(i, j, f).getCellType() == Cell.SMOKE)
						drawSmoke(g2d, i, j, t.getCell(i, j, f));
					g2d.translate(dx, 0);

				}
				g2d.translate(-(dx * t.length), dy);
			}
		}
		this.repaint();

	}

	protected void clear(Graphics g) {
		super.paintComponent(g);
	}

	protected Ellipse2D.Double getCircle() {
		return (agentFigure);
	}

	/*** Carolina **********************************************/
	public void ImageDrawing(URL imageSrc) {
		try {
			bi = ImageIO.read(imageSrc);

			w = bi.getWidth(null);
			h = bi.getHeight(null);
			if (bi.getType() != BufferedImage.TYPE_INT_RGB) {
				BufferedImage bi2 = new BufferedImage(w, h,
						BufferedImage.TYPE_INT_RGB);
				Graphics big = bi2.getGraphics();
				big.drawImage(bi, 0, 0, null);
				bi = bi2;
			}
		} catch (IOException e) {
			System.out.println("Image could not be read");
			System.exit(1);
		}
	}

	public GregorianCalendar getStartTime() {
		return startTime;
	}

	public void setStartTime() {
		this.startTime = new GregorianCalendar();
		this.info.setStartTime();
	}

	public void setStopTime() {
		this.stop = true;

	}

	public AuxInfo getInfo() {
		return info;
	}

	public void setInfo(AuxInfo info) {
		this.info = info;
	}

	public static boolean imBlocked(int x, int y, int f, Map t) {
		Cell up, down, right, left = null;

		int dy, dx = 0;
		int rows = t.length - 1;
		int cols = t.width - 1;

		if (y == 0 && x == 0 && f == 0) // in the superior corner first floor
		{
			try {
				// System.out.println("case 1");
				if (!t.getCell(x + 1, y, f).isFree()
						&& !t.getCell(x, y + 1, f).isFree())
					return true;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (y == 0 && x == 0 && f != 0) // in the superior corner, not in first
										// floor
		{
			try {
				// System.out.println("case 2");
				if(t.getCell(x, y, f)
						.getCellType() == Cell.DOOR){

					if (!t.getCell(x + 1, y, f).isFree()
						&& !t.getCell(x, y + 1, f).isFree()
						&& !t.getCell(rows, y, f - 1).isFree()
						&& t.getCell(rows, y, f - 1).getCellType() == Cell.STAIRS)
						return true;
				}
				if(t.getCell(x, y, f).getCellType() == Cell.DOOR 
						&& t.getCell(rows, y, f - 1)
						.getCellType() != Cell.STAIRS)
					
					return true;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (x == 0 && y == cols) // superior right corner
		{
			try {
				// System.out.println("case 3");

				if (!t.getCell(x + 1, y, f).isFree()
						&& !t.getCell(x, y - 1, f).isFree())
					return true;

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (y == cols && x == rows) // inferior corner right
		{
			try {
				// System.out.println("case 4" );
				if (!t.getCell(x, y - 1, f).isFree()
						&& !t.getCell(x - 1, y, f).isFree())
					return true;

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (y == 0 && x == rows) // left inferior corner
		{
			try {
				// System.out.println("case 5");

				if (!t.getCell(x, y + 1, f).isFree()
						&& !t.getCell(x - 1, y, f).isFree())
					return true;

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (x == rows && (y + 1) <= cols && y > 0) // last row
		{
			try {
				// System.out.println("case 6");
				if (!t.getCell(x - 1, y, f).isFree()
						&& !t.getCell(x, y + 1, f).isFree()
						&& !t.getCell(x, y - 1, f).isFree())
					return true;

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (y == 0 && (x + 1) <= rows && x > 0) // first column
		{
			try {
				// System.out.println("case 7");
				if (!t.getCell(x + 1, y, f).isFree()
						&& !t.getCell(x, y + 1, f).isFree()
						&& !t.getCell(x - 1, y, f).isFree())
					return true;

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (y == cols && (x + 1) <= rows && x > 0) // last column
		{
			try {
				// System.out.println("case 8");
				if (!t.getCell(x + 1, y, f).isFree()
						&& !t.getCell(x, y - 1, f).isFree()
						&& !t.getCell(x - 1, y, f).isFree()

				)
					return true;

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		// is a valid position

		if (y + 1 >= 0 && y - 1 >= 0)
			if (y + 1 <= cols) // colonna
				if (x - 1 >= 0)
					if (x + 1 <= rows)
						try {
							// System.out.println("case 9");

							if (!t.getCell(x - 1, y, f).isFree()
									&& !t.getCell(x + 1, y, f).isFree()
									&& !t.getCell(x, y - 1, f).isFree()
									&& !t.getCell(x, y + 1, f).isFree())
								return true;

						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

		return false;
	}

}
